import collections
from collections import abc
from types import MappingProxyType
from dis import dis
from unicodedata import name

# 1.泛映射类型
my_dict = {}
print(isinstance(my_dict, abc.Mapping))

tt = (1, 2, (30, 40))
print(hash(tt))
tl = (1, 2, [30, 40])
# print(hash(tl)) # TypeError 只有元组里面的值都是可散列才行
tf = (1, 2, frozenset([30, 40]))
print(hash(tf))
# 构造函数
a = dict(one=1, two=2, three=3)
b = {'one': 1, 'two': 2, 'three': 3}
c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
d = dict([('two', 2), ('one', 1), ('three', 3)])
e = dict({'three': 3, 'one': 1, 'two': 2})
print(a == b == c == d == e)

# 2.字典推导
DIAL_CODES = [
    (86, 'China'),
    (91, 'India'),
    (1, 'United States'),
    (62, 'Indonesia'),
    (55, 'Brazil'),
    (92, 'Pakistan'),
    (880, 'Bangladesh'),
    (234, 'Nigeria'),
    (7, 'Russia'),
    (81, 'Japan'),
]

country_code = {country: code for code, country in DIAL_CODES}
print(country_code)
code_country = {code: country.upper() for country, code in country_code.items() if code < 66}
print(code_country)

# 3、常见方法 see index.py
# 4、弹性键查询 see index_default.py StrKeyDict0.py
# __missing__ 方法 在[key]找不到时有用 只对__getitem__有用 get()方法不影响

# 5、字典的变种
# collections.OrderedDict 有序
# collections.ChainMap 可以容纳数个不同的映射对象，然后在进行键查找操作的时候，当作一个整体被逐个查找，直到键被找到为止
# collections.Counter 键->整数计数器
ct = collections.Counter('abracadabra')
print(ct)
ct.update('aaaaazzz')
print(ct)
print(ct.most_common(2))
# colllections.UserDict 让用户继承

# 6.子类化UserDict 比继承dict 方便 StrKeyDict.py
# 7.不可变映射类型
# types 模块 MappingProxyType 返回一个只读的映射视图
# 如果对原映射 做出了改动，我们通过这个视图可以观察到，但是无法通过这个视图对原映射做出修改
d = {1: 'A'}
d_proxy = MappingProxyType(d)
print(d_proxy)
print(d_proxy[1])
# d_proxy[2]='x' # TypeError
d[2] = 'B'
print(d_proxy)
print(d_proxy[2])
# 8.集合论 集合唯一
l = ['spam', 'spam', 'eggs', 'spam']
print(set(l))
print(list(set(l)))
# set是不可散列的 frozenset可以
# a | b 合集   a & b 交集  a - b 差集
# found = len(needles & haystack)  needles在haystack 出现的次数 两个都是集合
# 空集必须set() 字面量 {1} {1,2}
s = {1}
print(type(s))
print(s)
print(s.pop())
print(s)
# 字面量要快于构造函数 (反汇编函数比较)
dis('{1}')
dis('set([1])')
# frozenset 只能用构造函数
print(frozenset(range(10)))
# 集合推导
# name(chr(i), '') ->  INVERTED QUESTION MARK LATIN CAPITAL LETTER A WITH GRAVE
print({chr(i) for i in range(32, 256) if 'SIGN' in name(chr(i), '')})
# 9.dict 和 set的背后
d1 = dict(DIAL_CODES)
print('d1:', d1.keys())
d2 = dict(sorted(DIAL_CODES))
print('d2', d2.keys())
d3 = dict(sorted(DIAL_CODES, key=lambda x: x[1]))
print('d3:', d3.keys())
assert d1 == d2 and d2 == d3
